﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using Word = Microsoft.Office.Interop.Word;
using System.IO;

namespace TSites.Offices
{
	public class WordObject
	{
		public static void ExportAndPrint(string templatePath, Dictionary<string, object> paramsHash,
			string savedFileName = null, bool isVisible = false, string printerName = null)
		{
			if (!File.Exists(templatePath) || paramsHash == null)
				return;

			// OBJECT OF MISSING "NULL VALUE"
			Object oMissing = Missing.Value;

			Word.Application oWordApp = null;
			Word.Document oWordDoc = null;
			try
			{
				// CREATING OBJECTS OF WORD AND DOCUMENT
				oWordApp = new Word.Application();
				oWordDoc = new Word.Document();

				// MAKING THE APPLICATION VISIBLE/INVISIBLE
				oWordApp.Visible = isVisible;

				//THE LOCATION OF THE TEMPLATE FILE ON THE MACHINE
				object oTemplatePath = templatePath;

				//ADDING A NEW DOCUMENT FROM A TEMPLATE
				oWordDoc = oWordApp.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);

				// FILL PARAMETERS INTO BOOKMARKS
				object paramValue;
				foreach (Word.Bookmark wordBookmark in oWordDoc.Bookmarks)
				{
					if (paramsHash.TryGetValue(wordBookmark.Name, out paramValue))
					{
						wordBookmark.Range.Text = paramValue.ToString();
					}
				}

				// Method of Payment
				if (paramsHash.TryGetValue("MethodOfPayment", out paramValue))
				{
					ProcessMethodOfPayment(oWordDoc, (List<AuditPaymentMethod>)paramValue);
				}

				if (!string.IsNullOrWhiteSpace(savedFileName))
				{
					//THE LOCATION WHERE THE FILE NEEDS TO BE SAVED
					Object oSaveAsFile = savedFileName;
					oWordDoc.SaveAs(ref oSaveAsFile, ref oMissing, ref oMissing, ref oMissing,
						ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
						ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
						ref oMissing, ref oMissing);
				}

				if (!string.IsNullOrWhiteSpace(printerName))
				{
					// SET PRINTER
					object oWordBasic = oWordApp.WordBasic;

					// FIRST ARG IS A PRINTER NAME
					object[] argValues = new object[] { printerName, 1 };
					string[] argNames = new string[] { "Printer", "DoNotSetAsSysDefault" };

					oWordBasic.GetType().InvokeMember("FilePrintSetup", BindingFlags.InvokeMethod, null,
						oWordBasic, argValues, null, null, argNames);

					// PRINT DOCUMENT
					oWordApp.PrintOut();
				}
			}
			catch { throw; }
			finally
			{
				if (!isVisible)
				{
					// Close website wordDoc2
					if (oWordDoc != null)
					{
						oWordDoc.Close(ref oMissing, ref oMissing, ref oMissing);
						Marshal.ReleaseComObject(oWordDoc);
						oWordDoc = null;
					}

					// close wordApp
					if (oWordApp != null)
					{
						oWordApp.Quit(ref oMissing, ref oMissing, ref oMissing);
						System.Runtime.InteropServices.Marshal.ReleaseComObject(oWordApp);
						oWordApp = null;
					}

					GC.Collect();
				}
			}
		}

		private static void ProcessMethodOfPayment(Word.Document oWordDoc, List<AuditPaymentMethod> paymentMethods)
		{
			// create table
			Word.Table tbl = oWordDoc.Tables[2];
			int count;
			if (paymentMethods == null || (count = paymentMethods.Count) == 0)
			{
				tbl.Delete();
			}
			else
			{
				object oBeforeRow = Type.Missing;
				// we have 1 template row
				// so, should be begining with 2
				for (int i = 2; i <= count; i++)
				{
					tbl.Rows.Add(ref oBeforeRow); 
				}

				Word.Row wRow;
				// fill data
				for (int i = 1; i <= count; i++)
				{
					wRow = tbl.Rows[i];
					wRow.Cells[1].Range.Text = paymentMethods[i - 1].Time;
					wRow.Cells[2].Range.Text = paymentMethods[i - 1].MethodOfPayment;
				}
			}
		}
	}

	public class AuditPaymentMethod
	{
		public string Time { get; set; }
		public string MethodOfPayment { get; set; }
	}
}
